package band.wukong.practice.java.core.topic.encoding;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * Desc:  从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念
 * Refer: http://www.codeceo.com/article/java-date-operation.html
 *
 * @author wukong(wukonggg@139.com)
 */
public class AboutEncoding {

    /**
     * show unicode of string
     *
     * @param s
     */
    public static void showUnicode(String s) {
        for (int i = 0; i < s.length(); i++) {
//            System.out.printf("s.charAt:       \\u%x", (int)s.charAt(i));
            System.out.printf("s.codePointAt: \\u%x,    ", s.codePointAt(i));
        }
        System.out.println();
    }

    /**
     * show bytes of string in charset
     *
     * @param s
     * @param charset
     * @throws IOException
     */
    public static void showBytes(String s, String charset) throws IOException {
        for (byte b : s.getBytes(charset)) {
            System.out.printf("0x%x,    ", b);
        }
        System.out.println();
    }

    /**
     * convert string from a charset to another charset
     *
     * @throws UnsupportedEncodingException
     */
    public static void convert() throws UnsupportedEncodingException {
        //假设这是以字节流方式从文件中读取到的数据（GBK编码）
        byte[] gbkData = {(byte) 0xc4, (byte) 0xe3, (byte) 0xba, (byte) 0xc3};

        //转换到Unicode
        String tmp = new String(gbkData, "GBK");

        //从Unicode转换到Big5编码
        byte[] big5Data = tmp.getBytes("Big5");

        System.out.println("big5Data = " + new String(big5Data, "Big5"));
    }

    /**
     * mock jsp encoding lost
     *
     * @param charset
     * @throws UnsupportedEncodingException
     */
    public static void mockJspEncodingLost(String charset) throws UnsupportedEncodingException {
        //JSP框架收到6个字节的数据
        byte[] data = {(byte) 0xe4, (byte) 0xbd, (byte) 0xa0, (byte) 0xe5, (byte) 0xa5, (byte) 0xbd};

        //打印原始数据
        showBytes4mockJspEncodingLost(data);
        //JSP框架假设它是ISO-8859-1的编码，生成一个String对象
        String tmp = new String(data, charset);

        //**************JSP框架部分结束********************

        //开发者拿到后打印它发现是6个欧洲字符，而不是预期的"你好"
        System.out.println("  ISO解码的结果：" + tmp);

        //因此首先要得到原始的6个字节的数据（反查ISO-8859-1的代码页）
        byte[] utfData = tmp.getBytes(charset);

        //打印还原的数据
        showBytes4mockJspEncodingLost(utfData);

        //开发者知道它是UTF-8编码的，因此用UTF-8的代码页，重新构造String对象
        String result = new String(utfData, "UTF-8");
        //再打印，正确了！
        System.out.println("  UTF-8解码的结果：" + result);

    }

    private static void showBytes4mockJspEncodingLost(byte[] data) {
        for (byte b : data)
            System.out.printf("0x%x ", b);
        System.out.println();
    }

}
